<template>
	<view :style="{width:'100%',height:'100%',position: 'relative'}">
		<view v-if="ready" :style="{left:'20px', right:'20px',top:'20px',position: 'absolute'}">
			<button type="primary" :style="{marginBottom:'15px'}" @click="anchorStartLive">主播开播</button>
			
			直播间列表<br>
			<button v-for="(item,index) in liveRoomList"
			        :key="index"
			        type="primary"
			        :style="{marginBottom:'15px'}"
			        @click.native="audienceEnterRoom(item)">{{`${item.user_nicename}(${item.uid})`}}
			</button>
		</view>
		<view v-else :style="{left:'0px', right:'0px',top:'0px',bottom:'0px',overflow:'hidden',position: 'absolute'}">
			
			<div ref="anchorView"
			     :style="{width:'100%',height:'100%',position: 'absolute'}">
			</div>
			<div ref="audienceView"
			     :style="{width:'140px',height:'200px',right:'0px',top:'0px',bottom:'0px', overflow:'scroll',position: 'absolute'}">
			
			</div>
			<view v-show="isAudience" :style="{width:'80px',left:'15px',bottom:'15px',position: 'absolute'}">
				<button type="primary" @click="audienceMic">{{isUpMic?"下麦":"上麦"}}</button>
			</view>
		
		</view>
		
		
		<view>
			<uni-popup ref="applyMicDialog" type="dialog">
				<uni-popup-dialog type="info"
				                  cancelText="拒绝"
				                  confirmText="同意"
				                  title="连麦申请"
				                  :content="applyMicInfo.tip"
				                  @confirm="applyMicInfo.onAgree"
				                  @close="applyMicInfo.onRefuse">
				
				</uni-popup-dialog>
			</uni-popup>
		</view>
	
	
	</view>

</template>

<script>
    import TXLivePusher from '../../static/js/txsdk/TXLivePusher-1.0.2.min'
    import Toast from "../../components/common/toast";
    import Http from "../../utils/http";
    import MD5 from "md5";
    import io from "socket.io-client";
    import FlvJs from 'flv.js'

    export default {
        name: "txsdk",
        data() {
            const self = uni.getStorageSync('user')//自己
            return {
                liveRoomList: [],//直播间列表
                uid: self.id,//自己的id
                self,
                ready: true,
                anchorInfo: {//主播的推流信息
                    uid: '',
                    stream: '',
                    pusher: null,
                    player: null,
                },
                audienceInfo: {//观众的上麦信息
                    uid: '',
                    pusher: null,
                    player: null,
                },
                applyMicInfo: {//上麦观众的申请
                    tip: '',
                    onAgree: null,
                    onRefuse: null,
                }
            }
        },
        computed: {
            isAudience() {//自己是否是观众
                return this.anchorInfo.uid !== '' && this.anchorInfo.uid !== this.uid
            },
            isUpMic() {//自己是否上麦了
                return this.hasUpMic()
            }
        },
        methods: {

            /**
             * 获取直播间列表
             */
            getLiveRoomList() {
                const that = this
                Http.request(Http.getMainHomeLive, {'p': '1'}, {
                    onSucc(code, msg, info) {
                        that.liveRoomList = info[0].list
                    }
                })
            },

            /**
             * 观众播放主播的流
             */
            playAnchor(playUrl) {
                console.log("腾讯sdk:", "播放主播的流：", playUrl)
                const videoEl = document.createElement('video')
                videoEl.id = this.anchorInfo.uid
                videoEl.setAttribute('width', '100%')
                videoEl.setAttribute('height', '100%')
                videoEl.setAttribute('autoplay', false)
                videoEl.setAttribute('loop', this.isVideo)
                videoEl.setAttribute('preload', 'auto')
                videoEl.setAttribute('controls', false)
                // videoEl.setAttribute('object-fit', 'cover') 加不加都一样
                videoEl.setAttribute('x5-video-player-type', 'h5')
                videoEl.setAttribute('x5-video-orientation', 'portrait')
                videoEl.setAttribute('webkit-playsinline', true)
                videoEl.setAttribute('playsinline', true)
                videoEl.setAttribute('x5-video-player-fullscreen', true)
                this.$refs.anchorView.appendChild(videoEl)

                const flvPlayer = FlvJs.createPlayer({
                    type: playUrl.endsWith('.flv') ? 'flv' : 'mp4',
                    url: playUrl
                }, {
                    enableWorker: false,
                    lazyLoadMaxDuration: 3 * 60,
                    seekType: 'range',
                });
                flvPlayer.attachMediaElement(videoEl);
                flvPlayer.load();
                setTimeout(() => {
                    flvPlayer.play();
                }, 1000)

                this.anchorInfo.player = flvPlayer

            },


            /**
             * 主播播放观众上麦的流
             */
            playAudienceMic(uid, playUrl) {
                console.log("腾讯sdk:", "播放观众连麦的流：", playUrl)
                const videoEl = document.createElement('video')
                videoEl.id = uid
                videoEl.setAttribute('width', '100%')
                videoEl.setAttribute('height', '100%')
                videoEl.setAttribute('autoplay', false)
                videoEl.setAttribute('loop', this.isVideo)
                videoEl.setAttribute('preload', 'auto')
                videoEl.setAttribute('controls', false)
                // videoEl.setAttribute('object-fit', 'cover') 加不加都一样
                videoEl.setAttribute('x5-video-player-type', 'h5')
                videoEl.setAttribute('x5-video-orientation', 'portrait')
                videoEl.setAttribute('webkit-playsinline', true)
                videoEl.setAttribute('playsinline', true)
                videoEl.setAttribute('x5-video-player-fullscreen', true)
                this.$refs.audienceView.appendChild(videoEl)

                const flvPlayer = FlvJs.createPlayer({
                    type: 'flv',
                    url: playUrl
                }, {
                    enableWorker: false,
                    lazyLoadMaxDuration: 3 * 60,
                    seekType: 'range',
                });
                flvPlayer.attachMediaElement(videoEl);
                flvPlayer.load();
                setTimeout(() => {
                    flvPlayer.play();
                }, 1000)

                this.audienceInfo.player = flvPlayer

            },


            /**
             * 连接socket
             */
            connectSocket(socketUrl) {
                console.log("腾讯sdk:", "连接socket", socketUrl)


                const socket = io(socketUrl, {
                    autoConnect: false,
                    transports: ['websocket']
                });
                this.socket = socket
                socket.on('connect', () => {
                    console.log("腾讯sdk:", "socket--连接socket成功--->")
                    socket.emit("conn", {
                        'uid': this.self.id,
                        'token': this.self.token,
                        'mobileid': '111111222222',
                        'liveuid': this.anchorInfo.uid,
                        'roomnum': this.anchorInfo.uid,
                        'stream': this.anchorInfo.stream,
                    })
                });
                socket.on('connect_error', error => {
                    console.log("腾讯sdk:", "socket--连接socket报错--->", error)
                });
                socket.on('error', error => {
                    console.log("腾讯sdk:", "socket--error--->", error)
                });
                socket.on("reconnect", () => {
                    console.log("腾讯sdk:", "socket--reconnect--->")
                })
                socket.on("ping", () => {
                    console.log("腾讯sdk:", "socket--ping--->")
                })
                socket.on('disconnect', () => {
                    console.log("腾讯sdk:", "socket--disconnect--->")
                });
                socket.on("conn", (data) => {
                    console.log("腾讯sdk:", "socket--conn--->", data)
                })
                socket.on("broadcastingListen", msgs => {
                    for (let i = 0; i < msgs.length; i++) {
                        this.showSocketMsg(JSON.parse(msgs[i]).msg[0])
                    }
                })

                socket.connect()
            },


            /**
             * 收到socket消息
             */
            showSocketMsg(msg) {
                console.log("腾讯sdk:", "收到socket消息--->", msg)
                const method = msg['_method_']
                if (method === 'ConnectVideo') {//连麦
                    if (msg.action === '1') {//观众发起连麦请求
                        if (this.uid === this.anchorInfo.uid) {
                            this.showApplyMicDialog(msg.uid, msg.uname)
                        }
                    }
                    if (msg.action === '2') {//主播同意观众的连麦
                        if (this.uid === msg.touid) {
                            this.audienceGetMicPushUrl()
                        }
                    } else if (msg.action === '4') {//收到观众上麦的流
                        this.audienceInfo.uid = msg.uid
                        if (this.uid === this.anchorInfo.uid) {
                            let playUrl = msg.playurl
                            playUrl = playUrl.substring(0, playUrl.indexOf('?'))
                            playUrl = playUrl.replace("rtmp:", "https:")
                            playUrl = playUrl + ".flv"
                            this.playAudienceMic(msg.uid, playUrl)
                        }
                    } else if (msg.action === '5') {//观众断开连麦
                        if (this.audienceInfo.uid === msg.uid) {
                            if (this.uid === msg.uid) {//断开连麦的是自己
                                this.destroyLivePusher(this.audienceInfo.pusher, () => {
                                    this.audienceInfo.pusher = null
                                })
                                const container = document.getElementById(this.uid)
	                            if (container){
                                    container.remove()
	                            }
                            } else if (this.uid === this.anchorInfo.uid) {//主播关闭观众的播放器
                                this.destroyPlayer(this.audienceInfo.player, () => {
                                    this.audienceInfo.player = null
                                    console.log("腾讯sdk:", "销毁观众连麦的播放器")
                                })
                                const videoEl = document.getElementById(msg.uid);
                                if (videoEl){
                                    videoEl.remove()
                                }
                            }
                            this.audienceInfo.uid = ''
                            Toast.show(`${msg.uname}退出连麦`)
                        }
                    } else if (msg.action === '6') {//主播将观众下麦
                        if (this.audienceInfo.uid === msg.touid) {
                            if (this.uid === msg.touid) {//断开连麦的是自己
                                this.destroyLivePusher(this.audienceInfo.pusher, () => {
                                    this.audienceInfo.pusher = null
                                })
                                const container = document.getElementById(this.uid)
	                            if (container){
                                    container.remove()
	                            }
                            }  else if (this.uid === this.anchorInfo.uid){//主播关闭观众的播放器
                                this.destroyPlayer(this.audienceInfo.player, () => {
                                    this.audienceInfo.player = null
                                    console.log("腾讯sdk:", "销毁观众连麦的播放器")
                                })
                                const videoEl = document.getElementById(msg.uid);
                                if (videoEl){
                                    videoEl.remove()
                                }
                            }
                            this.audienceInfo.uid = ''
                            Toast.show(`${msg.uname}退出连麦`)
                        }
                    } else if (msg.action === '8') {
                        Toast.show('主播在忙')
                    }
                }
            },


            /**
             * 发送socket消息
             */
            sendSocketMsg(data) {
                const msg = {
                    'retcode': '000000',
                    'retmsg': 'ok',
                    'msg': [data],
                }
                console.log("腾讯sdk:", "发送socket消息--->", msg)
                this.socket.emit('broadcast', msg)
            },


            /**
             * 显示观众连麦申请的弹窗
             */
            showApplyMicDialog(touid, touname) {
                this.applyMicInfo.tip = `${touname}请求连麦`
                this.applyMicInfo.onAgree = () => {
                    Toast.show("同意对方上麦")
                    this.sendSocketMsg({
                        '_method_': 'ConnectVideo',
                        'action': '2',
                        'msgtype': '10',
                        'touid': touid,
                        'uid': this.uid,
                        'uname': this.self.user_nicename,
                        'level': this.self.level,
                        'ct': '',
                    })
                }
                this.applyMicInfo.onRefuse = () => {
                    Toast.show("拒绝对方上麦")
                    this.sendSocketMsg({
                        '_method_': 'ConnectVideo',
                        'action': '3',
                        'msgtype': '10',
                        'touid': touid,
                        'uid': this.uid,
                        'uname': this.self.user_nicename,
                        'level': this.self.level,
                        'ct': '',
                    })
                }
                this.$nextTick(() => {
                    this.$refs.applyMicDialog.open()
                })

            },


            /**
             * 主播开播
             */
            anchorStartLive() {
                this.anchorInfo.uid = this.uid
                this.ready = false
                this.$nextTick(() => {
                    this.createPusher(this.createRoom, this.changeLive)
                })
            },
            /**
             * 主播创建直播间
             */
            createRoom() {
                console.log("腾讯sdk:", "创建直播间")
                const that = this
                Http.request(Http.createRoom,
                    {
                        'uid': this.self.id,
                        'token': this.self.token,
                        'user_nicename': this.self.user_nicename,
                        'avatar': this.self.avatar,
                        'avatar_thumb': this.self.avatar_thumb,
                        'city': '泰安市',
                        'province': '山东省',
                        'lat': '36.178052',
                        'lng': '117.086263',
                        'title': '推流测试',
                        'liveclassid': '3',
                        'type': '0',
                        'type_val': '0',
                        'isshop': '0',
                        'thumb': '',
                        'live_type': '0',
                        'deviceinfo': 'web推流',
                    },
                    {
                        onSucc(code, msg, info) {
                            console.log("腾讯sdk:", "开播信息：", info)
                            const obj = info[0]
                            that.anchorInfo.stream = obj.stream
                            let pushUrl = obj.push.replace("rtmp:", "webrtc:")
                            console.log("腾讯sdk:", "pushUrl：", pushUrl)
                            that.anchorInfo.pusher.startPush(pushUrl)
                            console.log("腾讯sdk:", "主播开始推流")
                            that.connectSocket(obj.chatserver)
                            that.anchorSetMic()
                        }
                    }
                )

            },


            /**
             * 主播设置是否允许观众发起连麦
             */
            anchorSetMic() {
                console.log("腾讯sdk:", "设置允许观众发起连麦")
                Http.request(Http.anchorSetMic, {
                    'uid': this.self.id,
                    'token': this.self.token,
                    'ismic': '1'
                }, {
                    onSucc(code, msg, info) {
                        console.log("腾讯sdk:", "允许观众连麦：", info)
                    }
                })
            },

            /**
             * 主播开播成功后修改直播状态
             */
            changeLive() {
                console.log("腾讯sdk:", "请求changeLive接口")
                Http.request(Http.changeLive, {
                    'uid': this.self.id,
                    'token': this.self.token,
                    'stream': this.anchorInfo.stream,
                    'status': '1'
                }, {
                    onSucc(code, msg, info) {
                        console.log("腾讯sdk:", "changeLive：", info)
                    }
                })
            },

            /**
             * 主播关闭直播间
             */
            stopLiveRoom() {
                console.log("腾讯sdk:", "请求stopRoom接口")
                let now = new Date()
                let time = parseInt(now.getTime() / 1000)
                let str = `stream=${this.anchorInfo.stream}&time=${time}&token=${this.self.token}&uid=${this.self.id}&76576076c1f5f657b634e966c8836a06`
                let sign = MD5(str)

                Http.request(Http.stopRoom, {
                    'uid': this.self.id,
                    'token': this.self.token,
                    'stream': this.anchorInfo.stream,
                    time, sign
                }, {
                    onSucc(code, msg, info) {
                        console.log("腾讯sdk:", "stopRoom：", info)
                    }
                })
            },


            /**
             * 创建推流器，开启摄像头预览
             * @param onFirstFrame 采集成功音视频第一帧回调
             * @param onPushSucc 成功推流回调
             */
            createPusher(onFirstFrame, onPushSucc) {
                const livePusher = new TXLivePusher()
                //设置视频的分辨率
                livePusher.setProperty('setVideoResolution', {width: 640, height: 480})
                // 设置视频的帧率
                livePusher.setProperty('setVideoFPS', 15);
                //设置视频的码率
                livePusher.setProperty('setVideoBitrate', 900);
                //设置音频的采样率
                livePusher.setProperty('setAudioSampleRate', 48000)
                //设置音频的码率
                livePusher.setProperty('setAudioBitrate', 40)

                let hasVideo = false;
                let hasAudio = false;
                let isPush = false;
                const that = this

                livePusher.setObserver({
                    //直播推流器错误通知，推流器出现错误时，会回调该通知。
                    onError(code, msg, extraInfo) {
                        console.log("腾讯sdk:", "onError：", code, msg)
                    },
                    //直播推流器警告通知
                    onWarning(code, msg, extraInfo) {
                        console.log("腾讯sdk:", "onWarning：", code, msg)
                    },
                    //首帧音频采集完成的回调通知
                    onCaptureFirstAudioFrame() {
                        console.log("腾讯sdk:", "首帧音频采集完成")
                        hasAudio = true;
                        if (hasVideo && !isPush) {
                            isPush = true;
                            if (onFirstFrame) {
                                onFirstFrame()
                            }
                        }
                    },
                    //首帧视频采集完成的回调通知
                    onCaptureFirstVideoFrame() {
                        console.log("腾讯sdk:", "首帧视频采集完成")
                        hasVideo = true;
                        if (hasAudio && !isPush) {
                            isPush = true;
                            if (onFirstFrame) {
                                onFirstFrame()
                            }
                        }
                    },
                    //推流器连接状态回调通知
                    onPushStatusUpdate(status, msg, extraInfo) {
                        console.log("腾讯sdk:", "推流器连接状态回调:---status-->", status)
                        if (status === 2) {//推流成功
                            if (onPushSucc) {
                                onPushSucc()
                            }
                        }
                    },
                    //直播推流器统计数据回调，主要是 WebRTC 相关的统计数据，不同浏览器返回的数据可能不一致。
                    onStatisticsUpdate(data) {
                        // console.log("腾讯sdk:", "直播推流器统计数据回调：", data)
                    }
                })

                // 打开摄像头
                livePusher.startCamera();
                // 打开麦克风
                livePusher.startMicrophone();
                // let deviceManager = livePusher.getDeviceManager();
                // deviceManager.getDevicesList("audio").then(res => {
                //     console.log("腾讯sdk:", "getDevicesList：", res)
                // })
                //

                // deviceManager.getCurrentDevice().then(res => {
                //     console.log("腾讯sdk:", "getCurrentDevice：", res)
                // })

                if (this.uid === this.anchorInfo.uid) {//自己是主播
                    livePusher.setRenderView(this.$refs.anchorView);
                    this.anchorInfo.pusher = livePusher
                } else {
                    const container = document.createElement('div')
                    container.id = this.uid;
                    container.style.width = '100%'
                    container.style.height = '100%'
                    this.$refs.audienceView.append(container);
                    livePusher.setRenderView(container);
                    this.audienceInfo.pusher = livePusher
                }

            },


            /**
             * 观众进入房间
             */
            audienceEnterRoom(liveData) {
                const that = this
                Http.request(Http.enterRoom, {
                    'uid': this.self.id,
                    'token': this.self.token,
                    'city': '泰安市',
                    'liveuid': liveData.uid,
                    'mobileid': '1110000',
                    'stream': liveData.stream
                }, {
                    onSucc(code, msg, info) {
                        const obj = info[0]
                        that.anchorInfo.uid = liveData.uid
                        that.anchorInfo.stream = liveData.stream
                        that.ready = false
                        that.connectSocket(obj.chatserver)
                        that.$nextTick(() => {
                            let pull = obj.pull
                            pull = pull.replace("http:", "https:")
                            that.playAnchor(pull)
                        })
                    }
                })
            },

            //自己是否上麦了
            hasUpMic() {
                return this.audienceInfo.uid !== '' && this.audienceInfo.uid === this.uid
            },
            /**
             * 观众上麦和下麦
             */
            audienceMic() {
                if (this.hasUpMic()) {//下麦
                    //发送下麦的消息
                    this.sendSocketMsg({
                        '_method_': 'ConnectVideo',
                        'action': '5',
                        'msgtype': '10',
                        'uid': this.uid,
                        'uname': this.self.user_nicename,
                        'ct': '',
                    })
                } else {//上麦
                    //发送上麦的申请
                    this.sendSocketMsg({
                        '_method_': 'ConnectVideo',
                        'action': '1',
                        'msgtype': '10',
                        'uid': this.uid,
                        'uname': this.self.user_nicename,
                        'level': this.self.level,
                        'sex': this.self.sex,
                        'uhead': this.self.avatar,
                        'ct': '',
                    })
                }
            },

            /**
             * 观众获取上麦的推拉流地址
             */
            audienceGetMicPushUrl() {
                const that = this
                Http.request(Http.getMicPushUrl, {
                    'uid': this.uid
                }, {
                    onSucc(code, msg, info) {
                        const obj = info[0]
                        let pushUrl = obj.pushurl
                        const playUrl = obj.playurl
                        that.createPusher(() => {
                            pushUrl = pushUrl.replace("rtmp:", "webrtc:")
                            console.log("腾讯sdk:", "观众开始推流pushUrl：", pushUrl)
                            that.audienceInfo.pusher.startPush(pushUrl)
                            that.audienceInfo.uid = that.uid
                        }, () => {
                            console.log("腾讯sdk:", "观众推流成功")
                            that.sendSocketMsg({
                                '_method_': 'ConnectVideo',
                                'action': '4',
                                'msgtype': '10',
                                'uid': that.uid,
                                'uname': that.self.user_nicename,
                                'level': that.self.level,
                                'playurl': playUrl,
                                'ct': '',
                            })
                        })


                    }
                })
            },

            /**
             * 销毁播放器
             */
            destroyPlayer(player, callback) {
                if (player) {
                    player.pause();
                    player.unload();
                    player.detachMediaElement();
                    player.destroy();
                    if (callback) {
                        callback()
                    }
                }
            },


            /**
             * 销毁推流器
             */
            destroyLivePusher(livePusher, callback) {
                if (livePusher) {
                    if (livePusher.isPushing()) {
                        livePusher.stopPush()
                        console.log("腾讯sdk:", "停止推流")
                    }
                    // 关闭摄像头
                    livePusher.stopCamera()
                    // 关闭麦克风
                    livePusher.stopMicrophone()
                    console.log("腾讯sdk:", "关闭摄像头和麦克风")
                    //离开页面或者退出时，清理 SDK 实例
                    livePusher.destroy()
                    console.log("腾讯sdk:", "清理 SDK 实例")
                    if (callback) {
                        callback()
                    }
                }
            },


            /**
             * 离开房间
             */
            leaveRoom() {
                if (this.socket) {
                    this.socket.disconnect()
                    console.log("腾讯sdk:", "断开socket")
                }
                let livePusher = null
                if (this.uid === this.anchorInfo.uid) {//自己是主播
                    this.destroyPlayer(this.audienceInfo.player, () => {
                        this.audienceInfo.player = null
                        console.log("腾讯sdk:", "销毁观众连麦的播放器")
                    })
                    this.destroyLivePusher(this.anchorInfo.pusher)
                    this.stopLiveRoom()
                } else {
                    this.destroyPlayer(this.anchorInfo.player, () => {
                        this.anchorInfo.player = null
                        console.log("腾讯sdk:", "销毁主播的播放器")
                    })
                    this.destroyLivePusher(this.audienceInfo.pusher)
                }

            }
        },
        mounted() {
            console.log(TXLivePusher)
            this.getLiveRoomList()
        },
        beforeDestroy() {
            this.leaveRoom()
        }
    }
</script>

<style scoped>
</style>
